package br.com.ava.core.funcionario;

import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import br.com.ava.core.ConstantesMensagens;
import br.com.ava.core.infra.excecao.NegocioException;
import br.com.ava.core.infra.mensagem.Mensagem;
import br.com.ava.core.infra.persistencia.AbstractMediator;

public class FuncionarioMediator extends AbstractMediator<Funcionario> {

	private static final long serialVersionUID = 1L;
	private FuncionarioDAO dao;

	// private CodificadorSenhaSpring codificadorSenhaSpring;

	@Transactional(isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
	public Funcionario buscarPorEmail(String email) {
		return dao.buscarPorEmail(email);
	}

	@Transactional(isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
	public Funcionario buscarPorEmailSenha(String email, String senha) {
		return dao.buscarPorEmailSenha(email, criptografaSenha(senha));
	}

	@Override
	@Transactional(isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
	public void salvar(Funcionario funcionario) {
		validarInclusao(funcionario);
		funcionario.setSenha(criptografaSenha(funcionario.getSenha()));
		funcionario.setIdFuncionario(obterProximoId());
		getDao().salvar(funcionario);
	}

	@Override
	protected void validarInclusao(Funcionario funcionario)
			throws NegocioException {
		super.validarInclusao(funcionario);
		validarCamposObrigatorios(funcionario);
		validarFormatoTelefone(funcionario.getTelefone());
	}

	private void validarCamposObrigatorios(Funcionario funcionario) {
		List<Mensagem> mensagens = funcionario.validar();

		if (funcionario.getSenha() != null
				&& StringUtils.isBlank(funcionario.getSenha())) {
			mensagens.add(new Mensagem(
					ConstantesMensagens.MSG_ERRO_CAMPO_OBRIGATORIO, "Senha"));
		}

		if (funcionario.getCpf() != null
				&& StringUtils.isBlank(funcionario.getCpf())) {
			mensagens.add(new Mensagem(
					ConstantesMensagens.MSG_ERRO_CAMPO_OBRIGATORIO, "CPF"));
		}

		if (funcionario.getNome() != null
				&& StringUtils.isBlank(funcionario.getNome())) {
			mensagens.add(new Mensagem(
					ConstantesMensagens.MSG_ERRO_CAMPO_OBRIGATORIO, "Nome"));
		}

		if (funcionario.getEmail() != null
				&& StringUtils.isBlank(funcionario.getEmail())) {
			mensagens.add(new Mensagem(
					ConstantesMensagens.MSG_ERRO_CAMPO_OBRIGATORIO, "E-mail"));
		}

		if (funcionario.getRg() != null
				&& StringUtils.isBlank(funcionario.getRg())) {
			mensagens.add(new Mensagem(
					ConstantesMensagens.MSG_ERRO_CAMPO_OBRIGATORIO, "RG"));
		}

		if (!mensagens.isEmpty()) {
			throw new NegocioException(mensagens);
		}
	}

	private void validarFormatoTelefone(String telefone) {
		List<Mensagem> mensagens = new ArrayList<Mensagem>();

		if (telefone.length() != 13) {
			mensagens.add(new Mensagem(
					ConstantesMensagens.MSG_ERRO_CAMPO_TELEFONE_NAO_FORMATADO));
		} else {
			if (!telefone.contains("(") || !telefone.contains(")")
					|| !telefone.contains("-")) {
				mensagens
						.add(new Mensagem(
								ConstantesMensagens.MSG_ERRO_CAMPO_TELEFONE_NAO_FORMATADO));
			}
		}

		if (!mensagens.isEmpty()) {
			throw new NegocioException(mensagens);
		}
	}

	@Transactional(isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
	public List<Funcionario> consultarTodos() {
		return dao.listar();
	}

	@Transactional(isolation = Isolation.DEFAULT, rollbackFor = Exception.class)
	public Funcionario buscar(Integer id) {
		return dao.buscar(id);
	}

	private Integer obterProximoId() {
		Integer retorno = dao.obterIdAtual();
		if (retorno == null) {
			retorno = 1;
		} else {
			retorno++;
		}
		return retorno;
	}

	@Override
	public FuncionarioDAO getDao() {
		return dao;
	}

	public void setDao(FuncionarioDAO dao) {
		this.dao = dao;
	}

	/**
	 * Criptografa a senha em md5.
	 * 
	 * @param usuario
	 *            .
	 * @return senha criptografada - String.
	 * @throws NoSuchAlgorithmException
	 */
	private String criptografaSenha(String senha) {
		MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("MD5");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		md.update(senha.getBytes());
		BigInteger hash = new BigInteger(1, md.digest());
		String senhaCriptografada = hash.toString(16);
		return senhaCriptografada;
	}

}
